﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DDFolderSync
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.IO;
    using System.Linq;
    using System.Security.AccessControl;
    using System.Security.Cryptography.X509Certificates;
    using System.Text.RegularExpressions;
    using System.Threading;
    using System.Xml.Linq;
    using Microsoft.WindowsAzure;
    using Microsoft.WindowsAzure.ServiceRuntime;
    using Microsoft.WindowsAzure.StorageClient;
    using System.Threading.Tasks;
    using System.Configuration;
    using System.Diagnostics;
    using smarx.WazStorageExtensions;
    public class Entry
    {
        public DateTime LocalLastModified { get; set; }

        public DateTime CloudLastModified { get; set; }

        public bool IsDirectory { get; set; }
    }

    public class SyncService
    {
        public static readonly IList<string> FileExtensionsToExclude = new List<string>();
        //private string localPath;
        private IList<string> globalAbsolutePathOfFoldersToInclude;

        public IList<string> GlobalAbsolutePathOfFoldersToInclude
        {
            get { return globalAbsolutePathOfFoldersToInclude; }
            set { globalAbsolutePathOfFoldersToInclude = value; }
        }
        // private CloudBlobContainer container;
        // private Dictionary<string, Entry> entries;
        private Dictionary<string, Dictionary<string, Entry>> entryCollectionPerPath;
        private Dictionary<string, CloudBlobContainer> folderContainer;
        private IList<string> directoriesToExclude = new List<string>();

        public IList<string> DirectoriesToExclude
        {
            get { return directoriesToExclude; }
            set { directoriesToExclude = value; }
        }
        // Default sync is 5 mins
        private int _syncTimeInSecs = 300;
        public static readonly RetryPolicy RETRY_POLICY = RetryPolicies.Retry(3, TimeSpan.Zero);
        public const int BLOB_UPLOAD_TIMEOUT_SECS = 120;


        static readonly SyncService instance = new SyncService();

        // Explicit static constructor to tell C# compiler
        // not to mark type as beforefieldinit
        static SyncService()
        {
        }

        SyncService()
        {
        }

        public static SyncService Instance
        {
            get
            {
                return instance;
            }
        }

        public int SyncTimeInSecs
        {
            get { return _syncTimeInSecs; }
            set { _syncTimeInSecs = value; }
        }

        private bool _syncInParallel = true;

        public bool SyncInParallel
        {
            get { return _syncInParallel; }
            set { _syncInParallel = value; }
        }

        private CloudBlob _syncLockBlob = null;

        public CloudBlob SyncLockBlob
        {
            get { return _syncLockBlob; }
            set { _syncLockBlob = value; }
        }
     
        public static string SitesRoot = "";

        public void CreateSyncLockBlob()
        {
            try
            {
                string containerName = "ddsynclocksdonotremove";

                CloudBlobContainer container = CloudStorageAccount.Parse(SyncService.GetConfigValueAsString("com.dynamicdeploy.ddfoldersync.DataConnectionString")).CreateCloudBlobClient().GetContainerReference(containerName);

                container.CreateIfNotExist();

                string blobName = (RoleEnvironment.IsAvailable) ?string.Format("{0}/{1}/{2}", RoleEnvironment.DeploymentId,RoleEnvironment.CurrentRoleInstance.Role.Name, RoleEnvironment.CurrentRoleInstance.Id):"ddfilesynclock";

                var newBlob = container.GetBlobReference(blobName);
                newBlob.UploadText("Dynamic Deploy Rocks!");

                SyncLockBlob = newBlob;

            }
            catch (Exception ex)
            {

                Trace.TraceError("Error creating sync lock blob " + ex.Message);

            }



        }
        public void RunContinuously()
        {
            try
            {
                this.SyncForever(TimeSpan.FromSeconds(SyncTimeInSecs));
            }
            catch (Exception ex)
            {

                Trace.TraceError("Error starting sync engine (RunContinuously) " + ex.Message);
            }

        }


        public static string AppRoot = "";


        public static string RoleRoot = "";
     
        public static string ExpandKeywords(string buffer)
        {
            if (RoleEnvironment.IsAvailable)
            {
                buffer = buffer.Replace("$approot$", AppRoot);
                buffer = buffer.Replace("$deploymentid$", RoleEnvironment.DeploymentId);
                buffer = buffer.Replace("$roleinstanceid$", RoleEnvironment.CurrentRoleInstance.Id);
                buffer = buffer.Replace("$computername$", Environment.MachineName);
                buffer = buffer.Replace("$guid$", Guid.NewGuid().ToString());
                buffer = buffer.Replace("$now$", DateTime.Now.ToString());
                buffer = buffer.Replace("$roleroot$", Environment.GetEnvironmentVariable("RoleRoot"));

                if (!string.IsNullOrEmpty(SitesRoot))
                {

                    buffer = buffer.Replace("$sitesroot$", SitesRoot);
                }
            }
            return buffer;
        }

        public static void FillEnvironmentVariables()
        {
            if (RoleEnvironment.IsAvailable)
            {
                try
                {
                    RoleRoot = Environment.GetEnvironmentVariable("RoleRoot");

                    AppRoot = Environment.GetEnvironmentVariable("RoleRoot") + @"\approot";
                    SitesRoot = Environment.GetEnvironmentVariable("RoleRoot") + @"\sitesroot";
                    if (!Directory.Exists(SitesRoot))
                    {
                        SitesRoot = null;
                        // May be WorkerRole
                        //AppRoot = Environment.GetEnvironmentVariable("RoleRoot") + @"\approot";
                        //SitesRoot = AppRoot;
                        if (RoleEnvironment.IsEmulated)
                        {

                            SitesRoot = AppRoot;
                        }
                    }

                    Trace.TraceInformation("Sites Root " + ((!string.IsNullOrEmpty(SitesRoot)) ? SitesRoot : "Seems to be a Worker Role"));
                    Trace.TraceInformation("AppRoot " + AppRoot);


                }
                catch (Exception ex)
                {
                    Trace.TraceError("Error retrieving environment variables and config variables in FillEnvironmentVariables() " + ex.Message);

                }
            }
        }

        private Dictionary<string, string> GetLocalStorageToSyncAbsolutePaths()
        {
            if (RoleEnvironment.IsAvailable)
            {
                try
                {
                    string[] absolutePathOfFoldersToIncludeInternal = GetConfigValueAsString("com.dynamicdeploy.ddfoldersync.LocalStorageToSync").Split(',', ';');
                    if (absolutePathOfFoldersToIncludeInternal != null && absolutePathOfFoldersToIncludeInternal.Length > 0)
                    {
                        Dictionary<string, string> pathsToSync = new Dictionary<string, string>();
                        foreach (string name in absolutePathOfFoldersToIncludeInternal)
                        {

                            pathsToSync.Add(name, RoleEnvironment.GetLocalResource(name).RootPath.TrimEnd('\\'));

                        }
                        return pathsToSync;
                    }
                }
                catch (Exception ex)
                {
                    Trace.TraceError("Error loading local storage. Still proceeding... " + ex.Message);
                }
            }
            return null;
        }

        public static void SetDirectoryPermissions(string absolutePath)
        {

            FileUtils.SetFileSystemRights(absolutePath, System.Security.AccessControl.FileSystemRights.CreateFiles | System.Security.AccessControl.FileSystemRights.Delete | System.Security.AccessControl.FileSystemRights.DeleteSubdirectoriesAndFiles | System.Security.AccessControl.FileSystemRights.Modify | System.Security.AccessControl.FileSystemRights.Synchronize | System.Security.AccessControl.FileSystemRights.Write | FileSystemRights.CreateDirectories );
           
        }

      
        /// <summary>
        /// morePathsToSync should be in format containerName=AbsolutePath
        /// </summary>
        /// <param name="morePathsToSync"></param>
        public bool OnStart(IList<string> morePathsToSync)
        {
            bool ret = true;
           
            FillEnvironmentVariables();
          //  string[] absolutePathOfFoldersToInclude = GetConfigValueAsString("AbsolutePathOfFoldersToInclude").Split(',', ';');
            string[] absolutePathOfFoldersToIncludeInternal = GetConfigValueAsString("com.dynamicdeploy.ddfoldersync.AbsolutePathOfFoldersToInclude").Split(',', ';');

           
            if(morePathsToSync == null)
            {
                morePathsToSync = new List<string>();
            }

            if (absolutePathOfFoldersToIncludeInternal != null && absolutePathOfFoldersToIncludeInternal.Count() > 0)
            {
                foreach (string abs in absolutePathOfFoldersToIncludeInternal)
                {
                    string a = ExpandKeywords(abs);
                    if (!morePathsToSync.Contains(a) )
                    {
                        morePathsToSync.Add(a);
                    }
                    else
                    {

                        Trace.TraceError("Directory is already scheduled for sync. " + a);
                    }

                }

            }

            if (morePathsToSync.Count > 0)
            {
                //Set write permissions on all the absolute folders

                SyncInParallel = bool.Parse(GetConfigValueAsString("com.dynamicdeploy.ddfoldersync.SyncDirectoriesInParallel"));

                //Global File Extensions to exclude
                if (!string.IsNullOrEmpty(GetConfigValueAsString("com.dynamicdeploy.ddfoldersync.ExcludeFollowingFileExtensions")))
                {

                    string[] exts = GetConfigValueAsString("com.dynamicdeploy.ddfoldersync.ExcludeFollowingFileExtensions").Split(',', ';');
                    if (exts != null && exts.Count() > 0)
                    {
                        foreach (string exclude in exts)
                        {
                            FileExtensionsToExclude.Add(ExpandKeywords(exclude));
                            Trace.TraceInformation("Extensions to exclude " + exclude);
                        }
                    }
                }

                //Paths to exclude from sync
                if (!string.IsNullOrEmpty(GetConfigValueAsString("com.dynamicdeploy.ddfoldersync.AbsolutePathOfFoldersToExclude")))
                {
                    try
                    {
                        string[] exDir = GetConfigValueAsString("com.dynamicdeploy.ddfoldersync.AbsolutePathOfFoldersToExclude").Split(',', ';');

                        if (exDir != null && exDir.Count() > 0)
                        {
                            foreach (string exclude in exDir)
                            {
                                DirectoriesToExclude.Add(ExpandKeywords(exclude));
                                Trace.TraceInformation("Directory to exclude " + exclude);
                            }

                        }
                    }
                    catch (Exception ez)
                    {
                        Trace.TraceError("Exception parsing directories to exclude from configuration file " + ez.Message);
                    }
                }
                if (DirectoriesToExclude == null)
                {

                    DirectoriesToExclude = new List<string>();
                }

                
                // this.entries = new Dictionary<string, Entry>();
                entryCollectionPerPath = new Dictionary<string, Dictionary<string, Entry>>();
                folderContainer = new Dictionary<string, CloudBlobContainer>();
                globalAbsolutePathOfFoldersToInclude = new List<string>();

                foreach (string folderPath in morePathsToSync)
                {
                    try
                    {
                        string fp = ExpandKeywords(folderPath);
                        string[] folderContainerArr = fp.Split('=');
                        if (folderContainerArr != null && folderContainerArr.Length > 1)
                        {
                            string path = folderContainerArr[1];
                            Trace.TraceInformation("Trying to configure monitoring for " + path);

                            if (!Directory.Exists(path))
                            {
                                Trace.TraceError("Directory does not exist yet. " + path);
                              
                                    return false;
                              
    
                                                           
                            }
                            else 
                            {

                                CloudBlobContainer container = CloudStorageAccount.Parse(GetConfigValueAsString("com.dynamicdeploy.ddfoldersync.DataConnectionString")).CreateCloudBlobClient().GetContainerReference(folderContainerArr[0]);
                                container.CreateIfNotExist();
                                Trace.TraceInformation(string.Format("Container {0} maps to directory {1}", folderContainerArr[0], path));
                                folderContainer.Add(path, container);
                                Trace.TraceInformation("Added path for monitoring " + path);

                                entryCollectionPerPath.Add(path, new Dictionary<string, Entry>());
                                Trace.TraceInformation("Added path to entries collection " + path);
                                SetDirectoryPermissions(path);
                                Trace.TraceInformation("Set directory permissions for " + path);

                                globalAbsolutePathOfFoldersToInclude.Add(path);
                                Trace.TraceInformation("Watching folder " + path);
                            }
                           

                        }
                        else
                        {

                            throw new ArgumentException("Container Pair not found for folder " + folderPath);
                        }

                    }
                    catch (Exception ex)
                    {
                        Trace.TraceError(string.Format("Error configuring path {0}. Exception {1}", folderPath, ex.Message));

                        return false;
                    }

                }

                //Add Local Storage 

                Dictionary<string, string> localStorage = GetLocalStorageToSyncAbsolutePaths();
                if (localStorage != null && localStorage.Count > 0)
                {
                    foreach (string storageName in localStorage.Keys)
                    {
                        string path = localStorage[storageName];
                        try
                        {
                            Trace.TraceInformation("Trying to configure monitoring for " + path);
                            if (Directory.Exists(path))
                            {
                                string containerName = storageName;
                                CloudBlobContainer container = CloudStorageAccount.Parse(GetConfigValueAsString("com.dynamicdeploy.ddfoldersync.DataConnectionString")).CreateCloudBlobClient().GetContainerReference(containerName);
                                container.CreateIfNotExist();
                                Trace.TraceInformation(string.Format("Container {0} maps to directory {1}", containerName, path));
                                folderContainer.Add(path, container);
                                Trace.TraceInformation("Added path for monitoring " + path);
                                entryCollectionPerPath.Add(path, new Dictionary<string, Entry>());
                                Trace.TraceInformation("Added path to entries collection " + path);
                                SetDirectoryPermissions(path);
                                Trace.TraceInformation("Set directory permissions for " + path);
                                globalAbsolutePathOfFoldersToInclude.Add(path);

                                Trace.TraceInformation("Watching folder " + path);
                            }
                            else
                            {
                                Trace.TraceError("Local Storage does not exist yet. " + path);
                                    return false;
                               
                               
                            }
                        }
                        catch (Exception ex)
                        {
                            Trace.TraceError(string.Format("Error configuring path {0}. Exception {1}", path, ex.Message));
                            return false;
                        }

                    }

                }

                Trace.TraceInformation("Configured folders for synchronization.");
                int temp;
                if (int.TryParse(GetConfigValueAsString("com.dynamicdeploy.ddfoldersync.SyncCheckWithBlobInSecs"), out temp))
                {
                    if (temp > 0)
                    {

                        SyncTimeInSecs = temp;

                    }
                }


                try
                {
                    Trace.TraceInformation("Sync Time in secs " + SyncTimeInSecs);

                    Stopwatch st = new Stopwatch();
                    st.Start();
                    Trace.TraceInformation("Initializing First Sync.");

                    this.Sync();
                    st.Stop();
                    Trace.TraceInformation("Finished First Sync. Elapsed Time in seconds =" + st.Elapsed.TotalSeconds);

                }
                catch (Exception ex)
                {
                    Trace.TraceError("Error starting first sync " + ex.Message);
                    return false;
                }


            }

            return ret;
        }

        public void SyncLocal(string localPath)
        {
            try
            {
                HashSet<string> seen = new HashSet<string>();
                HashSet<string> newCerts = new HashSet<string>();
                Dictionary<string, Entry> entries = entryCollectionPerPath[localPath];
                CloudBlobContainer container = folderContainer[localPath];
                foreach (var thing in this.EnumerateLocalEntries(localPath))
                {
                    try
                    {
                        var path = thing.Item1;
                        var entry = thing.Item2;

                        seen.Add(path);


                        if (!entries.ContainsKey(path) || entries[path].LocalLastModified < entry.LocalLastModified)
                        {
                            var newBlob = container.GetBlobReference(path);
                            if (entry.IsDirectory)
                            {
                                newBlob.Metadata["IsDirectory"] = "true";
                                newBlob.UploadByteArray(new byte[0], new BlobRequestOptions() { RetryPolicy = RETRY_POLICY });
                            }
                            else //can do explicit ignore here
                            {

                                using (var stream = File.Open(Path.Combine(localPath, path), FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete))
                                {
                                    newBlob.UploadFromStream(stream, new BlobRequestOptions() { RetryPolicy = RETRY_POLICY, Timeout = TimeSpan.FromSeconds(BLOB_UPLOAD_TIMEOUT_SECS) });
                                }
                            }

                            entry.CloudLastModified = newBlob.Properties.LastModifiedUtc;
                            try
                            {
                                entries[path] = entry;
                            }
                            catch (Exception)
                            {

                                //TODO: Access exception is thrown when collection is modified in a threaded environment
                            }
                        }

                    }
                    catch (Exception ex)
                    {

                       Trace.TraceError(string.Format("Error synchronizing path {0}. Exception:{1}", thing.Item1, ex.Message));
                    }
                }

                foreach (var path in entries.Keys.Where(k => !seen.Contains(k)).ToArray())
                {
                   
                        if (string.IsNullOrEmpty(Path.GetDirectoryName(path)) && Path.GetExtension(path).ToLowerInvariant() == ".pfx")
                        {
                            // leave these alone
                            continue;
                        }

                        try
                        {

                            container.GetBlobReference(path).Delete();
                        }
                        catch (Exception)
                        {
                            // ignore if the blob's already gone
                        }

                        try
                        {

                            entries.Remove(path);
                        }
                        catch (Exception)
                        {

                            //TODO: Access exception is thrown when collection is modified in a threaded environment
                        }

                  
                }

                seen = new HashSet<string>();

                foreach (var blob in container.ListBlobs(new BlobRequestOptions { UseFlatBlobListing = true, BlobListingDetails = BlobListingDetails.Metadata, Timeout = TimeSpan.FromSeconds(30) }).OfType<CloudBlob>())
                {
                    var path = blob.Uri.ToString().Substring(container.Uri.ToString().Length + 1);
                    var entry = new Entry { IsDirectory = blob.Metadata["IsDirectory"] == "true", CloudLastModified = blob.Properties.LastModifiedUtc };

                    seen.Add(path);

                    if (!entries.ContainsKey(path) || entries[path].CloudLastModified < entry.CloudLastModified)
                    {
                        if (entry.IsDirectory)
                        {
                            Directory.CreateDirectory(Path.Combine(localPath, path));
                        }
                        else if (string.IsNullOrEmpty(Path.GetDirectoryName(path)) && Path.GetExtension(path).ToLowerInvariant() == ".pfx")
                        {
                            newCerts.Add(Path.GetFileNameWithoutExtension(path).ToLowerInvariant());

                            // don't actually download this, no need to have the cert sitting around on disk
                            try
                            {
                                entries[path] = entry;
                            }
                            catch (Exception)
                            {

                                //TODO: Access exception is thrown when collection is modified in a threaded environment
                            }
                        }
                        else
                        {

                            Directory.CreateDirectory(Path.Combine(localPath, Path.GetDirectoryName(path)));

                            using (var stream = File.Open(Path.Combine(localPath, path), FileMode.Create, FileAccess.Write, FileShare.ReadWrite | FileShare.Delete))
                            {
                                blob.DownloadToStream(stream, new BlobRequestOptions() { RetryPolicy = RETRY_POLICY, Timeout = TimeSpan.FromSeconds(BLOB_UPLOAD_TIMEOUT_SECS) });
                            }

                        }

                        entry.LocalLastModified = new FileInfo(Path.Combine(localPath, path)).LastWriteTimeUtc;
                        try
                        {
                            entries[path] = entry;
                        }
                        catch (Exception)
                        {

                            //TODO: Access exception is thrown when collection is modified in a threaded environment
                        }
                    }
                }

                foreach (var path in entries.Keys.Where(k => !seen.Contains(k)))
                {
                    if (entries[path].IsDirectory)
                    {
                        Directory.Delete(Path.Combine(localPath, path), true);
                    }
                    else
                    {
                        if (string.IsNullOrEmpty(Path.GetDirectoryName(path)) && Path.GetExtension(path).ToLowerInvariant() == ".pfx")
                        {
                            newCerts.Add(Path.GetFileNameWithoutExtension(path).ToLowerInvariant());
                        }

                        try
                        {
                            File.Delete(Path.Combine(localPath, path));
                        }
                        catch
                        {
                        }
                    }

                    try
                    {
                        entries.Remove(path);
                    }
                    catch (Exception)
                    {

                        //TODO: Access exception is thrown when collection is modified in a threaded environment
                    }
                }

            }
            catch (Exception ex)
            {

                Trace.TraceError(string.Format("Error synchronizing path {0}. Exception:{1}", localPath, ex.Message));
            }

        }
        public void Sync()
        {
            if (SyncLockBlob == null)
                CreateSyncLockBlob();

            using (var arl = new AutoRenewLease(SyncLockBlob))
            {
                if (arl.HasLease)
                {
                    //This means that no one is running a sync 

                    if (SyncInParallel)
                    {

                        Parallel.ForEach<string>(globalAbsolutePathOfFoldersToInclude.Distinct(), localPath =>
                        // foreach(string localPath in absolutePathOfFoldersToInclude)
                        {
                            SyncLocal(localPath);

                        }); //for each folder
                    }
                    else
                    {

                        foreach (string localPath in globalAbsolutePathOfFoldersToInclude.Distinct())
                        {
                            SyncLocal(localPath);

                        } //for each folder

                    }

                }
                else
                {

                    Trace.TraceError("Could not acquire lease on blob " + SyncLockBlob.Uri.AbsoluteUri);

                    throw new Exception("Could not acquire lease for " + SyncLockBlob.Uri.AbsoluteUri);

                }

            }
        }

        private void SyncForever(TimeSpan interval)
        {
            while (true)
            {
                try
                {
                    
                    Stopwatch st = new Stopwatch();
                    st.Start();
                    Trace.TraceInformation("Initializing Sync.");

                    this.Sync();

                    st.Stop();
                    Trace.TraceInformation("Sync Complete. Elapsed Time in seconds =" + st.Elapsed.TotalSeconds);
                }
                catch (Exception e)
                {
                    // log all exceptions to blobs
                    //var errors = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue("com.dynamicdeploy.ddfoldersync.DataConnectionString")).CreateCloudBlobClient().GetContainerReference("ddfilesyncerrors");
                    //errors.CreateIfNotExist();
                    //var error = errors.GetBlobReference((DateTime.MaxValue - DateTime.UtcNow).Ticks.ToString("d19") + ".txt");
                    //error.Properties.ContentType = "text/plain";
                    //error.UploadText(e.ToString());
                    Trace.TraceError("Error in SyncForever " + e.Message);
                }

                Thread.Sleep(interval);
            }
        }

        //private IEnumerable<Tuple<string, Entry>> EnumerateLocalEntries(string localPath)
        //{
        //    foreach (var directory in Directory.EnumerateFileSystemEntries(localPath, "*", SearchOption.AllDirectories))
        //    {
        //        var relativePath = directory.Substring(localPath.Length + 1).Replace('\\', '/');
        //        var info = new FileInfo(directory);
        //        var entry = new Entry
        //        {
        //            LocalLastModified = info.LastWriteTimeUtc,
        //            IsDirectory = info.Attributes.HasFlag(FileAttributes.Directory)
        //        };

        //        if (IsExcluded(relativePath))
        //        {
        //            Trace.TraceInformation("Excluding the path " + relativePath);
        //            continue;

        //        }

        //        yield return new Tuple<string, Entry>(relativePath, entry);
        //    }
        //}

        private IEnumerable<Tuple<string, Entry>> EnumerateLocalEntries(string localPath)
        {
           
            foreach (var directory in Directory.EnumerateFileSystemEntries(localPath, "*", SearchOption.AllDirectories))
            {
                var relativePath = directory.Substring(localPath.Length + 1).Replace('\\', '/');
                var info = new FileInfo(directory);
                var entry = new Entry
                {
                    LocalLastModified = info.LastWriteTimeUtc,
                    IsDirectory = info.Attributes.HasFlag(FileAttributes.Directory)
                };

                if(FileExtensionsToExclude.Contains(Path.GetExtension(directory)))
                {
                    continue;
                }
                if (IsExcluded(directory, localPath))
                {
                    //Trace.TraceInformation("Excluding the path " + relativePath);
                    if (DirectoriesToExclude != null && !DirectoriesToExclude.Contains(directory))
                    {
                        DirectoriesToExclude.Add(directory);
                    }
                    continue;

                }

                yield return new Tuple<string, Entry>(relativePath, entry);
            }
        }

        private bool IsExcluded(string topPath)
        {

            string dirName = Path.GetDirectoryName(topPath);
            if (this.directoriesToExclude.Contains(topPath, StringComparer.OrdinalIgnoreCase) || this.directoriesToExclude.Contains(dirName, StringComparer.OrdinalIgnoreCase) )
                return true;

        

            return false;
        }

        private bool IsExcluded(string topPath, string baseDir)
        {
           // string dirPath = Path.GetDirectoryName(topPath);

            if (IsExcluded(topPath))
            {
                return true;

            }
            else
            {
                if (topPath == baseDir)
                {
                    return IsExcluded(topPath);
                }
                return IsExcluded(Path.GetDirectoryName(topPath), baseDir);

            }

          //  return false;

        }

        //private bool IsExcluded(string topPath)
        //{
        //    int position = topPath.IndexOf('/');

        //    if (position <= 0)
        //        return false;

        //    // Remove Site name
        //    string path = topPath.Substring(position + 1);

        //    if (this.directoriesToExclude.Contains(path, StringComparer.OrdinalIgnoreCase))
        //        return true;

        //    foreach (string toexclude in this.directoriesToExclude)
        //        if (path.StartsWith(toexclude + "/"))
        //            return true;

        //    return false;
        //}





        public static string GetConfigValueAsString(string configName)
        {
            return (RoleEnvironment.IsAvailable)
                                   ? RoleEnvironment.GetConfigurationSettingValue(configName)
                                   : ConfigurationManager.AppSettings[configName];

        }


    }

    /*
using System;
using System.IO;
using System.Security.AccessControl;

namespace FileSystemExample
{
    class FileExample
    {
        public static void Main()
        {
            try
            {
                string fileName = "test.xml";

                Console.WriteLine("Adding access control entry for "
                    + fileName);

                // Add the access control entry to the file.
                AddFileSecurity(fileName, @"DomainName\AccountName",
                    FileSystemRights.ReadData, AccessControlType.Allow);

                Console.WriteLine("Removing access control entry from "
                    + fileName);

                // Remove the access control entry from the file.
                RemoveFileSecurity(fileName, @"DomainName\AccountName",
                    FileSystemRights.ReadData, AccessControlType.Allow);

                Console.WriteLine("Done.");
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
        }

        // Adds an ACL entry on the specified file for the specified account.
        public static void AddFileSecurity(string fileName, string account,
            FileSystemRights rights, AccessControlType controlType)
        {


            // Get a FileSecurity object that represents the
            // current security settings.
            FileSecurity fSecurity = File.GetAccessControl(fileName);

            // Add the FileSystemAccessRule to the security settings.
            fSecurity.AddAccessRule(new FileSystemAccessRule(account,
                rights, controlType));

            // Set the new access settings.
            File.SetAccessControl(fileName, fSecurity);

        }

        // Removes an ACL entry on the specified file for the specified account.
        public static void RemoveFileSecurity(string fileName, string account,
            FileSystemRights rights, AccessControlType controlType)
        {

            // Get a FileSecurity object that represents the
            // current security settings.
            FileSecurity fSecurity = File.GetAccessControl(fileName);

            // Remove the FileSystemAccessRule from the security settings.
            fSecurity.RemoveAccessRule(new FileSystemAccessRule(account,
                rights, controlType));

            // Set the new access settings.
            File.SetAccessControl(fileName, fSecurity);

        }
    }
}


*/
}
